package com.example.sys.attachment.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.core.po.BasePo;
import com.example.core.service.BaseCoreServiceImpl;
import com.example.core.utils.CollectionUtils;
import com.example.core.utils.DateTimeUtils;
import com.example.core.utils.StringUtils;
import com.example.core.vo.BaseVo;
import com.example.sys.attachment.dao.SysAttachmentDao;
import com.example.sys.attachment.po.ISysAttachment;
import com.example.sys.attachment.po.SysAttachment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/***
 * 附件的操作类
 */
@Service
public class SysAttachmentServiceImpl extends BaseCoreServiceImpl<SysAttachmentDao, SysAttachment> implements SysAttachmentService {

    Logger logger = LoggerFactory.getLogger(getClass());

    public static final String OCRKEY = "ocrKey";

    @Value("${file.service.class}")
    private String fileServiceClass;

    @Value("${file.service.clear.time}")
    private int clearTime;

    private SysFileService sysFileService;

    @Resource
    private SysAttachmentUpLoadListenerService sysAttachmentUpLoadListenerService;

    @Override
    public SysFileService getSysFileService() {
        if (this.sysFileService == null) {
            try {
                Class<?> clazz = Class.forName(fileServiceClass);
                this.sysFileService = (SysFileService) clazz.newInstance();
            } catch (Exception e) {
                logger.warn("附件服务类加载失败: " + e.getMessage());
            }
        }
        return this.sysFileService;
    }

    /***
     * 文件上传
     * @param file
     * @return
     * @throws Exception
     */
    @Override
    public SysAttachment upload(MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String path = getSysFileService().write(file);
        SysAttachment sysAttachment = new SysAttachment();
        String modelKey = request.getParameter(MODEL_KEY);
        if (StringUtils.isNotEmpty(modelKey)) {
            sysAttachment.setModelKey(Integer.parseInt(modelKey));
        }
        sysAttachment.setName(file.getOriginalFilename());
        sysAttachment.setLength(file.getSize());
        sysAttachment.setType(file.getContentType());
        sysAttachment.setPath(path);
        sysAttachment.recalculateFields();
        saveOrUpdate(sysAttachment);
        return sysAttachmentUpLoadListenerService.upLoad(request, sysAttachment, file.getBytes());
    }

    /***
     * 文件加载成流文件
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public byte[] read(String id) throws Exception {
        SysAttachment sysAttachment = getById(id);
        return getSysFileService().read(sysAttachment.getPath());
    }


    /***
     * 查询待清理的附件信息。
     * 上传超过12小时并没有还没有关联的附件信息。
     * @return
     */
    @Override
    public List<SysAttachment> findClearList() {
        QueryWrapper<SysAttachment> queryWrapper = new QueryWrapper<>();
        queryWrapper.le("create_time", DateTimeUtils.getTimeAddHour(-clearTime));
        queryWrapper.isNull("model_id");
        return list(queryWrapper);
    }

    /***
     * 删除附件并清理文件
     * @param sysAttachment
     * @throws Exception
     */
    @Override
    public void deleteAttachment(SysAttachment sysAttachment) throws Exception {
        getSysFileService().delete(sysAttachment.getPath());
        removeById(sysAttachment.getId());
    }

    /***
     * 保存的时候，判断附件.
     * @param po
     * @throws Exception
     */
    @Override
    public void save(BasePo po) throws Exception {
        if (po instanceof ISysAttachment) {
            List<SysAttachment> fileList = ((ISysAttachment) po).getFileList();
            for (SysAttachment sysAttachment : fileList) {
                sysAttachment.setModelId(po.getId());
                sysAttachment.setModelName(po.getClass().getName());
                saveOrUpdate(sysAttachment);
            }
        }
    }

    /***
     * 修改的时候，要对比文件
     * @param po
     * @throws Exception
     */
    @Override
    public void update(BasePo po) throws Exception {
        if (po instanceof ISysAttachment) {
            List<SysAttachment> oldList = findList(po.getId(), po.getClass().getName(), null);
            List<SysAttachment> newList = ((ISysAttachment) po).getFileList();
            //对比两个对象的共有的对象。
            if (oldList.isEmpty() || newList.isEmpty()) {
                if (oldList.isEmpty() && !newList.isEmpty()) {
                    for (SysAttachment sysAttachment : newList) {
                        sysAttachment.setModelId(po.getId());
                        sysAttachment.setModelName(po.getClass().getName());
                        sysAttachment.recalculateFields();
                        saveOrUpdate(sysAttachment);
                    }
                }
                if (!oldList.isEmpty() && newList.isEmpty()) {
                    this.delete(po);
                }
            } else {
                List<String> comList = CollectionUtils.common(oldList, newList);
                for (SysAttachment sysAttachment : newList) {
                    if (!comList.contains(sysAttachment.getId())) {
                        sysAttachment.setModelId(po.getId());
                        sysAttachment.setModelName(po.getClass().getName());
                        sysAttachment.recalculateFields();
                        saveOrUpdate(sysAttachment);
                    }
                }
                for (SysAttachment sysAttachment : oldList) {
                    if (!comList.contains(sysAttachment.getId())) {
                        deleteAttachment(sysAttachment);
                    }
                }
            }
        }
    }


    /****
     * 删除对象的时候，清理文件
     * @param po
     * @throws Exception
     */
    @Override
    public void delete(BasePo po) throws Exception {
        List<SysAttachment> list = findList(po.getId(), po.getClass().getName(), null);
        for (SysAttachment sysAttachment : list) {
            deleteAttachment(sysAttachment);
        }
    }

    @Override
    public void toVo(BasePo po, BaseVo vo) throws Exception {
        if (po instanceof ISysAttachment && vo instanceof ISysAttachment) {
            List<SysAttachment> list = findList(po.getId(), po.getClass().getName(), null);
            if (!list.isEmpty()) {
                ((ISysAttachment) vo).setFileList(list);
            }
        }
    }
}
